package com.itheima.pinda.file.storage;

import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.AppendFileStorageClient;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.pinda.base.R;
import com.itheima.pinda.file.domain.FileDeleteDO;
import com.itheima.pinda.file.dto.chunk.FileChunksMergeDTO;
import com.itheima.pinda.file.entity.File;
import com.itheima.pinda.file.properties.FileServerProperties;
import com.itheima.pinda.file.strategy.impl.AbstractChunkStrategy;
import com.itheima.pinda.file.strategy.impl.AbstractFileStrategy;
import com.itheima.pinda.utils.DateUtils;
import com.itheima.pinda.utils.StrPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

/**
 * FastDfs策略配置类
 *
 * @author:ivan.liu
 */
@Configuration
@Slf4j
@EnableConfigurationProperties(FileServerProperties.class)
@ConditionalOnProperty(name = "pinda.file.type",havingValue = "FAST_DFS")
public class FastDfsAutoConfigure {
    /**
     * FastDfs策略处理类
     */
    @Service
    public class FastDfsServiceImpl extends AbstractFileStrategy{

        @Autowired
        private FastFileStorageClient storageClient;

        /**
         * 文件上传
         * @param file
         * @param multipartFile
         * @throws Exception
         */
        @Override
        public void uploadFile(File file, MultipartFile multipartFile) throws Exception {
            //调用客户端对象将文件上传至服务器
            StorePath storePath = storageClient.uploadFile(multipartFile.getInputStream(), multipartFile.getSize(), file.getExt(), null);
            //设置相关信息保存数据库
            file.setUrl(fileProperties.getUriPrefix()+storePath.getFullPath());
            file.setGroup(storePath.getGroup());
            file.setPath(storePath.getPath());
        }

        /**
         * 文件删除
         * @param fileDeleteDO
         */
        @Override
        public void delete(FileDeleteDO fileDeleteDO) {
            //调用客户端对象将文件删除
            storageClient.deleteFile(fileDeleteDO.getGroup(), fileDeleteDO.getPath());
        }
    }

    /**
     * FastDFS分片文件策略处理类
     */
    @Service
    public class FastDFSChunkServiceImpl extends AbstractChunkStrategy{

        @Autowired
        private AppendFileStorageClient storageClient;
        @Autowired
        private FileServerProperties fileServerProperties;

        /**
         * 分片合并
         * @param files
         * @param fileName
         * @param fileChunksMergeDTO
         * @return
         * @throws Exception
         */
        @Override
        protected R<File> merge(List<java.io.File> files, String fileName, FileChunksMergeDTO fileChunksMergeDTO) throws Exception {
            StorePath storePath = null;
            for (int i = 0; i < files.size(); i++) {
                java.io.File chunkFile = files.get(i);
                if (i==0){
                    storePath = storageClient.uploadAppenderFile(null, FileUtils.openInputStream(chunkFile)
                            , chunkFile.length(), fileChunksMergeDTO.getExt());
                }else {
                    storageClient.appendFile(storePath.getGroup(),storePath.getPath()
                            ,FileUtils.openInputStream(chunkFile),chunkFile.length());
                }
            }
            if (storePath==null){
                //分片合并失败
                log.error("分片合并失败");
                return R.fail("分片合并失败");
            }
            String url = new StringBuilder(fileServerProperties.getUriPrefix())
                    .append(storePath.getFullPath())
                    .toString();
            File filePo = File.builder()
                    .url(url)
                    .group(storePath.getGroup())
                    .path(storePath.getPath())
                    .build();
            return R.success(filePo);
        }
    }
}
